#ifndef _VL_THREAD_POOL__H_
#define _VL_THREAD_POOL__H_


#include <mutex>
#include <memory>
#include <functional>
#include <condition_variable>
#include <vector>
#include <thread>
#include <queue>
#include "vl_buffer.h"

namespace VL {


class FutureBuilder;

class VLThreadPool;

/**
 * @Author: CimZzz
 * @Date: 2022-08-21 08:15:14
 * 
 * Future
 */
class VLFuture {
public:
	/**
	 * @Author: CimZzz
	 * @Date: 2022-08-21 15:17:36
	 * 
	 * 中断当前 Future 任务
	 */
	void interrupt();

	/**
	 * @Author: CimZzz
	 * @Date: 2022-08-21 08:17:08
	 * 
	 * 等待结果
	 */
	void wait();

	/**
	 * @Author: CimZzz
	 * @Date: 2022-08-21 08:17:50
	 * 
	 * 判断 Future 是否已经完成
	 * 
	 * @return 如果成功返回 true
	 */
	bool isCompleted();

	/**
	 * @Author: CimZzz
	 * @Date: 2022-08-21 08:17:50
	 * 
	 * 判断 Future 是否已经中断
	 * 
	 * @return 如果中断返回 true
	 */
	bool isInterrupted();

	/**
	 * @Author: CimZzz
	 * @Date: 2022-08-21 16:28:12
	 * 
	 * 获取数据, 否则抛出异常
	 */
	virtual void getOrThrow();

protected:
	/**
	 * @Author: CimZzz
	 * @Date: 2022-08-21 08:16:38
	 * 
	 * 保护构造函数
	 */
	explicit VLFuture();

	/**
	 * @Author: CimZzz
	 * @Date: 2022-08-21 08:18:15
	 * 
	 * 判断 Future 是否已经完成
	 */
	volatile bool completed;

	/**
	 * @Author: CimZzz
	 * @Date: 2022-08-21 15:15:47
	 * 
	 * 判断 Future 是否中断
	 */
	volatile bool interrupted;

	/**
	 * @Author: CimZzz
	 * @Date: 2022-08-21 08:15:54
	 * 
	 * 线程锁
	 */
	std::mutex mutex;

	/**
	 * @Author: CimZzz
	 * @Date: 2022-08-21 08:16:08
	 * 
	 * 条件变量
	 */
	std::condition_variable cond;
};

/**
 * @Author: CimZzz
 * @Date: 2022-08-21 08:14:35
 * 
 * 新版 Future 实现
 */
template<typename T, typename E>
class VLFutureCore: public VLFuture {
private:
	/**
	 * @Author: CimZzz
	 * @Date: 2022-08-21 15:02:20
	 * 
	 * 声明 Future 构建器为友元类
	 */
	friend class FutureBuilder;

	/**
	 * @Author: CimZzz
	 * @Date: 2022-08-21 14:48:15
	 * 
	 * 构造函数
	 */
	explicit VLFutureCore(): VLFuture() {

	}

public:

	/**
	 * @Author: CimZzz
	 * @Date: 2022-08-21 14:58:48
	 * 
	 * 设置 Future 结果
	 * 
	 * @param data 数据值
	 */
	void setData(const T& data) {
		std::unique_lock<std::mutex> locker(this->mutex);
		if(this->completed) {
			return;
		}
		this->completed = true;
		this->dataPtr = std::shared_ptr<T>(new T(data));
		this->cond.notify_all();
	}

	/**
	 * @Author: CimZzz
	 * @Date: 2022-08-21 14:58:13
	 * 
	 * 设置 Future 结果
	 * 
	 * @param dataPtr 数据指针
	 */
	void setData(T* dataPtr) {
		std::unique_lock<std::mutex> locker(this->mutex);
		if(this->completed || this->interrupted) {
			delete dataPtr;
			return;
		}
		this->completed = true;
		this->dataPtr = std::shared_ptr<T>(dataPtr);
		this->cond.notify_all();
	}

	/**
	 * @Author: CimZzz
	 * @Date: 2022-08-21 14:55:42
	 * 
	 * 设置 Future 结果
	 * 
	 * @param dataPtr 数据指针
	 */
	void setData(const std::shared_ptr<T>& dataPtr) {
		std::unique_lock<std::mutex> locker(this->mutex);
		if(this->completed || this->interrupted) {
			return;
		}
		this->completed = true;
		this->dataPtr = dataPtr;
		this->cond.notify_all();
	}

	/**
	 * @Author: CimZzz
	 * @Date: 2022-08-21 14:56:22
	 * 
	 * 设置 Future 异常
	 * 
	 * @param error 异常值
	 */
	void setError(const E& error) {
		std::unique_lock<std::mutex> locker(this->mutex);
		if(this->completed || this->interrupted) {
			return;
		}
		this->completed = true;
		this->errorPtr = std::shared_ptr<E>(new E(error));
		this->cond.notify_all();
	}

	/**
	 * @Author: CimZzz
	 * @Date: 2022-08-21 14:56:22
	 * 
	 * 设置 Future 异常
	 * 
	 * @param errorPtr 异常指针
	 */
	void setError(E* errorPtr) {
		std::unique_lock<std::mutex> locker(this->mutex);
		if(this->completed || this->interrupted) {
			delete errorPtr;
			return;
		}
		this->completed = true;
		this->errorPtr = std::shared_ptr<E>(errorPtr);
		this->cond.notify_all();
	}

	/**
	 * @Author: CimZzz
	 * @Date: 2022-08-21 14:56:22
	 * 
	 * 设置 Future 异常
	 * 
	 * @param errorPtr 异常指针
	 */
	void setError(const std::shared_ptr<E>& errorPtr) {
		std::unique_lock<std::mutex> locker(this->mutex);
		if(this->completed || this->interrupted) {
			return;
		}
		this->completed = true;
		this->errorPtr = errorPtr;
		this->cond.notify_all();
	}

	/**
	 * @Author: CimZzz
	 * @Date: 2022-08-21 14:54:23
	 * 
	 * 获取数据, 如果发生异常则会抛出异常
	 * 
	 */
	std::shared_ptr<T> getDataOrThrow() {
		std::unique_lock<std::mutex> locker(this->mutex);
		if(!this->interrupted) {
			if(this->completed) {
				if(this->dataPtr.get() != nullptr) {
					return this->dataPtr;
				} else if(this->errorPtr.get() != nullptr){
					throw *this->errorPtr;
				}
			} else {
				this->cond.wait(locker);
			}

			if(!this->interrupted) {
				if(this->dataPtr.get() != nullptr) {
					return this->dataPtr;
				} else if(this->errorPtr.get() != nullptr){
					throw *this->errorPtr;
				}
			}
		}
		return std::shared_ptr<T>(nullptr);
	}

	/**
	 * @Author: CimZzz
	 * @Date: 2022-08-21 13:12:06
	 * 
	 * 获取数据
	 * 
	 * @return 数据指针
	 */
	std::shared_ptr<T> getData() {
		std::unique_lock<std::mutex> locker(this->mutex);
		if(this->completed) {
			return this->dataPtr;
		} else if(!this->interrupted){
			this->cond.wait(locker);
		}
		if(this->interrupted) {
			return std::shared_ptr<T>(nullptr);
		} else {
			return this->dataPtr;
		}
	}

	/**
	 * @Author: CimZzz
	 * @Date: 2022-08-21 13:13:07
	 * 
	 * 获取异常
	 * 
	 * @return 异常指针
	 */
	std::shared_ptr<E> getException() {
		std::unique_lock<std::mutex> locker(this->mutex);
		if(this->completed) {
			return this->errorPtr;
		} else if(!this->interrupted) {
			this->cond.wait(locker);
		}

		if(this->interrupted) {
			return std::shared_ptr<E>(nullptr);
		} else {
			return this->dataPtr;
		}
	}

	/**
	 * @Author: CimZzz
	 * @Date: 2022-08-21 16:28:12
	 * 
	 * 获取数据, 否则抛出异常
	 */
	virtual void getOrThrow() {
		this->getDataOrThrow();
	}

private:
	/**
	 * @Author: CimZzz
	 * @Date: 2022-08-21 14:49:11
	 * 
	 * 数据指针
	 */
	typename std::shared_ptr<T> dataPtr;

	/**
	 * @Author: CimZzz
	 * @Date: 2022-08-21 14:49:23
	 * 
	 * 异常指针
	 */
	typename std::shared_ptr<E> errorPtr;
};

/**
 * @Author: CimZzz
 * @Date: 2022-08-21 15:01:36
 * 
 * Future 构建器
 */
class FutureBuilder {
private:
	/**
	 * @Author: CimZzz
	 * @Date: 2022-08-21 15:02:44
	 * 
	 * 私有构造函数, 禁止实例化
	 */
	explicit FutureBuilder() {

	}

public:

	/**
	 * @Author: CimZzz
	 * @Date: 2022-08-21 15:03:56
	 * 
	 * 构建 Future 对象
	 * 
	 * @return Future 指针
	 */
	template<typename T, typename E>
	static std::shared_ptr<VLFuture> build() {
		return std::shared_ptr<VLFuture>(new VLFutureCore<T,E>());
	}

	/**
	 * @Author: CimZzz
	 * @Date: 2022-08-21 14:47:10
	 * 
	 * 获取 Future 核心
	 * 
	 * @param futurePtr Future 指针
	 * 
	 * @return Future 核心
	 */
	template<typename T, typename E>
	static std::shared_ptr<VLFutureCore<T, E>> getCore(const std::shared_ptr<VLFuture>& futurePtr) {
		return std::static_pointer_cast<VLFutureCore<T, E>, VLFuture>(futurePtr);
	}
};

/**
 * @Author: CimZzz
 * @Date: 2022-08-21 15:06:37
 * 
 * 线程 Functor
 */
class VLThreadRunnable {
public:
	/**
	 * @Author: CimZzz
	 * @Date: 2022-06-23 14:39:23
	 * 
	 * 可执行回调
	 */
	using Runnable = std::function<void(Buffer*)>;

	/**
	 * @Author: CimZzz
	 * @Date: 2022-08-21 15:05:54
	 * 
	 * 携带 Future 的可执行回调
	 */
	using FutureRunnable = std::function<void(const std::shared_ptr<VLFuture>&, Buffer*)>;

	/**
	 * @Author: CimZzz
	 * @Date: 2022-08-21 15:11:24
	 * 
	 * 构造方法
	 * 
	 * @param runnable 可执行回调
	 */
	explicit VLThreadRunnable(Runnable runnable);

	/**
	 * @Author: CimZzz
	 * @Date: 2022-08-21 15:11:46
	 * 
	 * 构造方法
	 * 
	 * @param runnable 携带 Future 的可执行回调
	 */
	explicit VLThreadRunnable(FutureRunnable runnable);


private:

	/**
	 * @Author: CimZzz
	 * @Date: 2022-08-21 15:09:54
	 * 
	 * 线程执行方法
	 */
	void threadRun();

	/**
	 * @Author: CimZzz
	 * @Date: 2022-08-21 15:41:45
	 * 
	 * 中断
	 */
	void interrupt();

	friend class VLThreadPool;

	Buffer* buffer;
	Runnable runnable;
	FutureRunnable futureRunnable;
	std::shared_ptr<VLFuture> futurePtr;
};

/**
 * @Author: CimZzz
 * @Date: 2022-08-21 16:25:30
 * 
 * 线程 Future 管理器
 */
class ThreadFutureManager {
public:
	/**
	 * @Author: CimZzz
	 * @Date: 2022-08-21 16:25:55
	 * 
	 * 构造函数
	 */
	explicit ThreadFutureManager();

	/**
	 * @Author: CimZzz
	 * @Date: 2022-08-21 16:27:44
	 * 
	 * 获取数据, 否则抛出异常
	 */
	void getOrThrow();

	/**
	 * @Author: CimZzz
	 * @Date: 2022-08-21 16:26:58
	 * 
	 * 添加 Future
	 * 
	 * @param futurePtr Future 指针
	 */
	void addFuture(const std::shared_ptr<VLFuture>& futurePtr);

	/**
	 * @Author: CimZzz
	 * @Date: 2022-08-21 16:27:09
	 * 
	 * 获取 Future
	 * 
	 * @param index Future 下标
	 * 
	 * @return Future 指针
	 */
	std::shared_ptr<VLFuture> getFuture(unsigned int index);

private:

	std::vector<std::shared_ptr<VLFuture>> futureList;
};

/**
 * @Author: CimZzz
 * @Date: 2022-08-21 01:06:04
 * 
 * 新版线程池
 */
class VLThreadPool {
public:

	/**
	 * @Author: CimZzz
	 * @Date: 2022-08-21 15:10:39
	 * 
	 * 初始化线程池
	 * 
	 * @param threadCount 线程数
	 */
	void initThreadPool(unsigned int threadCount);

	/**
	 * @Author: CimZzz
	 * @Date: 2022-08-21 15:12:41
	 * 
	 * 执行线程回调
	 * 
	 * @param runnable 线程回调
	 */
	void exec(VLThreadRunnable::Runnable runnable);

	/**
	 * @Author: CimZzz
	 * @Date: 2022-08-21 15:13:57
	 * 
	 * 执行 Future 线程回调
	 * 
	 * @param runnable 线程回调
	 * 
	 * @return Future 指针
	 */
	template<typename T, typename E>
	std::shared_ptr<VLFuture> exec(VLThreadRunnable::FutureRunnable runnable) {
		auto ptr = std::shared_ptr<VLThreadRunnable>(new VLThreadRunnable(runnable));
		auto futurePtr = FutureBuilder::build<T, E>();
		ptr->futurePtr = futurePtr;
		this->exec(ptr);
		return futurePtr;
	}

	/**
	 * @Author: CimZzz
	 * @Date: 2022-08-21 15:58:00
	 * 
	 * 等待全部任务完成
	 */
	void waitForAllTaskDone();

	/**
	 * @Author: CimZzz
	 * @Date: 2022-08-21 17:07:33
	 * 
	 * 将后续任务添加到等待队列中
	 */
	void pendingTask();

	/**
	 * @Author: CimZzz
	 * @Date: 2022-08-21 17:07:51
	 * 
	 * 将等待队列中的任务放置到主消息队列中
	 */
	void continueTask();

	/**
	 * @Author: CimZzz
	 * @Date: 2022-08-21 15:14:57
	 * 
	 * 中断线程池中其他任务
	 */
	void clearTask();

	/**
	 * @Author: CimZzz
	 * @Date: 2022-08-21 15:29:34
	 * 
	 * 获取线程池单例指针
	 * 
	 * @return 线程池指针
	 */
	static VLThreadPool* getInstance();

private: 
	/**
	 * @Author: CimZzz
	 * @Date: 2022-08-21 01:07:12
	 * 
	 * 构造函数
	 */
	explicit VLThreadPool();

	/**
	 * @Author: CimZzz
	 * @Date: 2022-08-21 01:08:04
	 * 
	 * 析构函数
	 */
	~VLThreadPool();

	/**
	 * @Author: CimZzz
	 * @Date: 2022-08-21 15:40:01
	 * 
	 * 执行线程回调
	 * 
	 * @param runnable 线程回调
	 */
	void exec(const std::shared_ptr<VLThreadRunnable>& runnable);

	/**
	 * @Author: CimZzz
	 * @Date: 2022-08-21 01:08:19
	 * 
	 * 线程池单例对象
	 */
	static VLThreadPool instance;

	/**
	 * @Author: CimZzz
	 * @Date: 2022-08-21 15:32:06
	 * 
	 * 是否正在运行中
	 */
	volatile bool isRunning;

	/**
	 * @Author: CimZzz
	 * @Date: 2022-08-21 01:08:34
	 * 
	 * 是否已经初始化完成
	 */
	bool isInit;

	/**
	 * @Author: CimZzz
	 * @Date: 2022-08-21 17:08:23
	 * 
	 * 判断当前是否需要进行等待队列
	 */
	bool isPending;

	/**
	 * @Author: CimZzz
	 * @Date: 2022-08-21 15:55:56
	 * 
	 * 任务数
	 */
	volatile uint32_t taskCount;

	/**
	 * @Author: CimZzz
	 * @Date: 2022-06-23 15:29:04
	 * 
	 * 线程锁
	 */
	std::mutex mutex;

	/**
	 * @Author: CimZzz
	 * @Date: 2022-06-23 15:29:15
	 * 
	 * 条件变量
	 */
	std::condition_variable cond;

	/**
	 * @Author: CimZzz
	 * @Date: 2022-08-21 15:57:35
	 * 
	 * 任务全部完成条件变量
	 */
	std::condition_variable taskDoneCond;

	/**
	 * @Author: CimZzz
	 * @Date: 2022-06-23 15:22:41
	 * 
	 * 线程池列表
	 */
	std::vector<std::shared_ptr<std::thread>> threadList;

	/**
	 * @Author: CimZzz
	 * @Date: 2022-06-23 15:38:08
	 * 
	 * 可执行回调队列
	 */
	std::queue<std::shared_ptr<VLThreadRunnable>> runnableQueue;

	/**
	 * @Author: CimZzz
	 * @Date: 2022-06-23 15:38:08
	 * 
	 * 可执行回调等待队列
	 */
	std::queue<std::shared_ptr<VLThreadRunnable>> pendingQueue;
};

}

#endif // _VL_THREAD_POOL__H_
